package com.handu.luna.core.domain.promotion;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.PostLoad;
import javax.persistence.PrePersist;
import javax.persistence.Transient;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.Size;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.format.annotation.DateTimeFormat;

import com.handu.luna.core.domain.goods.Category;
import com.handu.luna.core.domain.goods.Goods;
import com.handu.luna.core.domain.search.ActivitiesSearch;
import com.handu.luna.core.domain.user.UserRank;

@Entity
public class Activities extends Promotion {
	
	public enum ActivitiesRange{
		ALL("全部商品"),CATBRAND("以下分类品牌"),GOODS("以下商品");
		public String description;	    
		ActivitiesRange(final String description) {
	        this.description = description;
	    }
	}
	
	public enum ActivitiesMethods{
		SUBTRACT("满减"),DISCOUNT("满折"),BUYGIVE("满购/满赠");
		public String description;	    
		ActivitiesMethods(final String description) {
	        this.description = description;
	    }
	}
	
	public static final String DELIMITER = ",";
	
	@Size(min=1,max=100, message="促销活动名称不能为空或超过100个字符")
	private String activitiesName;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date beginTime;
	@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
	private Date endTime;
	private String userRank;
	private ActivitiesRange activitiesRange;
	private String activitiesGoodsids;
	private String categorys;
	private int brands;
	private BigDecimal minAmount;
	private BigDecimal maxAmount;
	private ActivitiesMethods activitiesMethods;
	private BigDecimal methodsExt; //优惠方式数据
	private String methodsGoodsids;
	
	@Transient private List<Long> userRankIdList;
	@Transient private List<UserRank> userRankList;
	@Transient private List<Long> categorysIdList;
	@Transient private List<Category> categorysList;
	@Transient private Map<Goods,BigDecimal> methodsGoods;
	
	@Transient
	private List<Goods> activitiesGoods;
	
	public Activities(){};
	
	public Activities(String activitiesName, Date beginTime, Date endTime,
			ActivitiesRange activitiesRange, BigDecimal minAmount,
			BigDecimal maxAmount, ActivitiesMethods activitiesMethods, String activitiesGoodsids) {
		super();
		this.activitiesName = activitiesName;
		this.beginTime = beginTime;
		this.endTime = endTime;
		this.activitiesRange = activitiesRange;
		this.minAmount = minAmount;
		this.maxAmount = maxAmount;
		this.activitiesMethods = activitiesMethods;
		this.activitiesGoodsids = activitiesGoodsids;
	}
	@PostLoad
    public void init() {
        if(StringUtils.isNotBlank(userRank)) {
        	userRankList = new ArrayList<>();
        	userRankIdList = new ArrayList<>();
            for (String userRankStrId : this.strToList(userRank)) {
                long userRankId = Long.parseLong(userRankStrId);
                userRankIdList.add(userRankId);
                userRankList.add(context.getUserRankRepository().findOne(userRankId));
            }
        }
        if(StringUtils.isNotBlank(categorys)) {
        	categorysList = new ArrayList<>();
        	categorysIdList = new ArrayList<>();
            for (String categoryStrId : this.strToList(categorys)) {
                long categoryId = Long.parseLong(categoryStrId);
                categorysIdList.add(categoryId);
                categorysList.add(context.getCategoryRepository().findOne(categoryId));
            }
        }
        if(StringUtils.isNotBlank(methodsGoodsids)){
        	methodsGoods = new HashMap<>();
        	String[] strarray = methodsGoodsids.split(";");
        	for (int i = 0; i < strarray.length; i++){
                String[] goodarray = strarray[i].split(",");             
                Goods goods = context.getGoodsRepository().findOne(Long.parseLong(goodarray[0]));
                BigDecimal bd=new BigDecimal(goodarray[1]);
                bd=bd.setScale(2, BigDecimal.ROUND_HALF_UP); 
                methodsGoods.put(goods,bd); 
        	}
        }
    }

    @PrePersist
    public void prePersist() {
        if(CollectionUtils.isNotEmpty(userRankIdList)) {
        	userRank = this.listToStr(userRankIdList);
        }
        if(CollectionUtils.isNotEmpty(categorysIdList)) {
        	categorys = this.listToStr(categorysIdList);
        }
    }

    public void update() {
        prePersist();
        context.getActivitiesRepository().save(this);
    }

    public String listToStr(List<Long> list) {
        StringBuilder sb = new StringBuilder();
        for (Long id : list) {
            sb.append(String.valueOf(id)).append(DELIMITER);
        }
        return sb.toString();
    }

    public List<String> strToList(String arrayString) {
        List<String> list = new ArrayList<String>();
        for(String item : arrayString.split(DELIMITER)) {
            list.add(item);
        }
        return list;
    }
    
	public List<Long> getUserRankIdList() {
		return userRankIdList;
	}

	public void setUserRankIdList(List<Long> userRankIdList) {
		this.userRankIdList = userRankIdList;
	}

	public List<UserRank> getUserRankList() {
		return userRankList;
	}

	public void setUserRankList(List<UserRank> userRankList) {
		this.userRankList = userRankList;
	}

	public List<Long> getCategorysIdList() {
		return categorysIdList;
	}

	public void setCategorysIdList(List<Long> categorysIdList) {
		this.categorysIdList = categorysIdList;
	}

	public List<Category> getCategorysList() {
		return categorysList;
	}

	public void setCategorysList(List<Category> categorysList) {
		this.categorysList = categorysList;
	}

	public String getActivitiesName() {
		return activitiesName;
	}
	public void setActivitiesName(String activitiesName) {
		this.activitiesName = activitiesName;
	}
	public Date getBeginTime() {
		return beginTime;
	}
	public void setBeginTime(Date beginTime) {
		this.beginTime = beginTime;
	}
	public Date getEndTime() {
		return endTime;
	}
	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}
	public String getUserRank() {
		return userRank;
	}
	public void setUserRank(String userRank) {
		this.userRank = userRank;
	}
	public ActivitiesRange getActivitiesRange() {
		return activitiesRange;
	}
	public void setActivitiesRange(ActivitiesRange activitiesRange) {
		this.activitiesRange = activitiesRange;
	}
	
	public String getCategorys() {
		return categorys;
	}

	public void setCategorys(String categorys) {
		this.categorys = categorys;
	}

	public int getBrands() {
		return brands;
	}
	public void setBrands(int brands) {
		this.brands = brands;
	}
	public BigDecimal getMinAmount() {
		return minAmount;
	}
	public void setMinAmount(BigDecimal minAmount) {
		this.minAmount = minAmount;
	}
	public BigDecimal getMaxAmount() {
		return maxAmount;
	}
	public void setMaxAmount(BigDecimal maxAmount) {
		this.maxAmount = maxAmount;
	}
	public ActivitiesMethods getActivitiesMethods() {
		return activitiesMethods;
	}
	public void setActivitiesMethods(ActivitiesMethods activitiesMethods) {
		this.activitiesMethods = activitiesMethods;
	}
	public BigDecimal getMethodsExt() {
		return methodsExt;
	}
	public void setMethodsExt(BigDecimal methodsExt) {
		this.methodsExt = methodsExt;
	}

	public String getActivitiesGoodsids() {
		return activitiesGoodsids;
	}

	public void setActivitiesGoodsids(String activitiesGoodsids) {
		this.activitiesGoodsids = activitiesGoodsids;
	}

	public List<Goods> getActivitiesGoods() {
		if (StringUtils.isNotBlank(activitiesGoodsids)){
			activitiesGoods = context.getGoodsRepository().findAll(Goods.in(activitiesGoodsids));
        }
		return activitiesGoods;
	}

	public void setActivitiesGoods(List<Goods> activitiesGoods) {
		this.activitiesGoods = activitiesGoods;
	}

	public String getMethodsGoodsids() {
		return methodsGoodsids;
	}

	public void setMethodsGoodsids(String methodsGoodsids) {
		this.methodsGoodsids = methodsGoodsids;
	}
	

	public Map<Goods, BigDecimal> getMethodsGoods() {
		return methodsGoods;
	}

	public void setMethodsGoods(Map<Goods, BigDecimal> methodsGoods) {
		this.methodsGoods = methodsGoods;
	}
	
	

	@Override
	public String getStatus() {
		return initStatus(beginTime, endTime);
	}

	public String getSucessFlashMessage(){
		String messagePrefix = (null==this.getId() ?"添加" : "修改");
		try {
			return messagePrefix + this.getActivitiesName() + "成功。";
		} catch ( SecurityException e) {
			return messagePrefix + "成功。";
		}
	}
	
	public static Specification<Activities> selectCondition(ActivitiesSearch activitiesSearch) {
		return new Specification<Activities>() {
			@Override
			public Predicate toPredicate(Root<Activities> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				Predicate predicate = builder.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();
				
				if (StringUtils.isNotBlank(activitiesSearch.getSearchName())) {
					expressions.add(builder.or( builder.like(root.<String> get("activitiesName"), "%"+ activitiesSearch.getSearchName() + "%")));			
				}
				
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date1 = null;
				Date date2 = null;
				Date nowdate = null;
				Date now = new Date();
				String nowtime = sdf1.format( now );

				if(StringUtils.isNotBlank(activitiesSearch.getSearchBeginTime()) && StringUtils.isBlank(activitiesSearch.getSearchEndTime())){
					try {
						date1 = sdf.parse(activitiesSearch.getSearchBeginTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), date1)); 
				}
				
				if(StringUtils.isBlank(activitiesSearch.getSearchBeginTime())&& StringUtils.isNotBlank(activitiesSearch.getSearchEndTime())){
					try {
						date2 = sdf.parse(activitiesSearch.getSearchEndTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), date2)); 
				}

				if(StringUtils.isNotBlank(activitiesSearch.getSearchBeginTime()) && StringUtils.isNotBlank(activitiesSearch.getSearchEndTime())){
					
					try {
						date1 = sdf.parse(activitiesSearch.getSearchBeginTime());
						date2 = sdf.parse(activitiesSearch.getSearchEndTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), date1)); 
					expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), date2));
				}
				
				if(activitiesSearch.getActivitiesState()!=0){
					try {
						nowdate = sdf1.parse(nowtime);
					} catch (ParseException e) {
						e.printStackTrace();
					}
					if(activitiesSearch.getActivitiesState()==1){
						
						expressions.add(builder.lessThanOrEqualTo(root.get("beginTime"), nowdate)); 
						expressions.add(builder.greaterThanOrEqualTo(root.get("endTime"), nowdate));
						
					}else if(activitiesSearch.getActivitiesState()==2){
						
						expressions.add(builder.greaterThanOrEqualTo(root.get("beginTime"), nowdate));
						
					}else if(activitiesSearch.getActivitiesState()==3){
						
						expressions.add(builder.lessThanOrEqualTo(root.get("endTime"), nowdate)); 
					}
				}
				
				return query.where(predicate).getRestriction();

			}
		};
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void merge(String[] fields) {
		List<Long> userRankIdList = this.getUserRankIdList();
		List<Long> categorysIdList = this.getCategorysIdList();
		if(!this.isNew()){
			Object thisDomainInDB = null;
			try {
                thisDomainInDB = BeanUtils.cloneBean(((JpaRepository) getRepository()).findOne(this.getId()));
			} catch (IllegalAccessException | InstantiationException
					| InvocationTargetException | NoSuchMethodException e1) {
				logger.debug("error in copy merge a domain",e1);
			}			
			for(String field : fields){
				try {
                    String property = BeanUtils.getProperty(this,field);
                    if(field.endsWith("Date") || field.endsWith("beginTime") ||  field.endsWith("endTime")) {
                        Date date = new SimpleDateFormat("EE MMM dd HH:mm:ss 'CST' yyyy", java.util.Locale.US).parse(property);
                        BeanUtils.copyProperty(thisDomainInDB, field, date);
                    }else {
                        BeanUtils.copyProperty(thisDomainInDB, field, property);
                    }
				} catch (IllegalAccessException | InvocationTargetException
						| NoSuchMethodException e) {
					logger.debug("error in copy merge a domain",e);
				} catch (ParseException e) {
                    e.printStackTrace();
                }
            }
			try {
				BeanUtils.copyProperties(this, thisDomainInDB);
			} catch (IllegalAccessException | InvocationTargetException e) {
				logger.debug("error in copy merge a domain",e);
			}
		}
		this.setUserRankIdList(userRankIdList);
		this.setCategorysIdList(categorysIdList);
	}
	
	


}
